1 /*
2 * Javassist, a Java-bytecode translator toolkit.
3 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. Alternatively, the contents of this file may be used under
8 * the terms of the GNU Lesser General Public License Version 2.1 or later,
9 * or the Apache License Version 2.0.
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 */
16
17 package scouter.javassist.bytecode;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.DataInputStream;
21 import java.io.IOException;
22 import java.util.HashMap;
23 import java.util.Map;
24
25 import scouter.javassist.bytecode.AttributeInfo;
26 import scouter.javassist.bytecode.ConstPool;
27 import scouter.javassist.bytecode.AnnotationsAttribute.Copier;
28 import scouter.javassist.bytecode.AnnotationsAttribute.Parser;
29 import scouter.javassist.bytecode.AnnotationsAttribute.Renamer;
30 import scouter.javassist.bytecode.annotation.Annotation;
31 import scouter.javassist.bytecode.annotation.AnnotationsWriter;
32
33
34 /**
35 * A class representing <code>RuntimeVisibleAnnotations_attribute</code> and
36 * <code>RuntimeInvisibleAnnotations_attribute</code>.
37 *
38 * <p>To obtain an ParameterAnnotationAttribute object, invoke
39 * <code>getAttribute(ParameterAnnotationsAttribute.invisibleTag)</code>
40 * in <code>MethodInfo</code>.
41 * The obtained attribute is a
42 * runtime invisible annotations attribute.
43 * If the parameter is
44 * <code>ParameterAnnotationAttribute.visibleTag</code>, then the obtained
45 * attribute is a runtime visible one.
46 */
47 public class ParameterAnnotationsAttribute extends AttributeInfo {
48 /**
49 * The name of the <code>RuntimeVisibleParameterAnnotations</code>
50 * attribute.
51 */
52 public static final String visibleTag
53 = "RuntimeVisibleParameterAnnotations";
54
55 /**
56 * The name of the <code>RuntimeInvisibleParameterAnnotations</code>
57 * attribute.
58 */
59 public static final String invisibleTag
60 = "RuntimeInvisibleParameterAnnotations";
61 /**
62 * Constructs
63 * a <code>Runtime(In)VisibleParameterAnnotations_attribute</code>.
64 *
65 * @param cp constant pool
66 * @param attrname attribute name (<code>visibleTag</code> or
67 * <code>invisibleTag</code>).
68 * @param info the contents of this attribute. It does not
69 * include <code>attribute_name_index</code> or
70 * <code>attribute_length</code>.
71 */
72 public ParameterAnnotationsAttribute(ConstPool cp, String attrname,
73 byte[] info) {
74 super(cp, attrname, info);
75 }
76
77 /**
78 * Constructs an empty
79 * <code>Runtime(In)VisibleParameterAnnotations_attribute</code>.
80 * A new annotation can be later added to the created attribute
81 * by <code>setAnnotations()</code>.
82 *
83 * @param cp constant pool
84 * @param attrname attribute name (<code>visibleTag</code> or
85 * <code>invisibleTag</code>).
86 * @see #setAnnotations(Annotation[][])
87 */
88 public ParameterAnnotationsAttribute(ConstPool cp, String attrname) {
89 this(cp, attrname, new byte[] { 0 });
90 }
91
92 /**
93 * @param n the attribute name.
94 */
95 ParameterAnnotationsAttribute(ConstPool cp, int n, DataInputStream in)
96 throws IOException
97 {
98 super(cp, n, in);
99 }
100
101 /**
102 * Returns <code>num_parameters</code>.
103 */
104 public int numParameters() {
105 return info[0] & 0xff;
106 }
107
108 /**
109 * Copies this attribute and returns a new copy.
110 */
111 public AttributeInfo copy(ConstPool newCp, Map classnames) {
112 Copier copier = new Copier(info, constPool, newCp, classnames);
113 try {
114 copier.parameters();
115 return new ParameterAnnotationsAttribute(newCp, getName(),
116 copier.close());
117 }
118 catch (Exception e) {
119 throw new RuntimeException(e.toString());
120 }
121 }
122
123 /**
124 * Parses the annotations and returns a data structure representing
125 * that parsed annotations. Note that changes of the node values of the
126 * returned tree are not reflected on the annotations represented by
127 * this object unless the tree is copied back to this object by
128 * <code>setAnnotations()</code>.
129 *
130 * @return Each element of the returned array represents an array of
131 * annotations that are associated with each method parameter.
132 *
133 * @see #setAnnotations(Annotation[][])
134 */
135 public Annotation[][] getAnnotations() {
136 try {
137 return new Parser(info, constPool).parseParameters();
138 }
139 catch (Exception e) {
140 throw new RuntimeException(e.toString());
141 }
142 }
143
144 /**
145 * Changes the annotations represented by this object according to
146 * the given array of <code>Annotation</code> objects.
147 *
148 * @param params the data structure representing the
149 * new annotations. Every element of this array
150 * is an array of <code>Annotation</code> and
151 * it represens annotations of each method parameter.
152 */
153 public void setAnnotations(Annotation[][] params) {
154 ByteArrayOutputStream output = new ByteArrayOutputStream();
155 AnnotationsWriter writer = new AnnotationsWriter(output, constPool);
156 try {
157 int n = params.length;
158 writer.numParameters(n);
159 for (int i = 0; i < n; ++i) {
160 Annotation[] anno = params[i];
161 writer.numAnnotations(anno.length);
162 for (int j = 0; j < anno.length; ++j)
163 anno[j].write(writer);
164 }
165
166 writer.close();
167 }
168 catch (IOException e) {
169 throw new RuntimeException(e); // should never reach here.
170 }
171
172 set(output.toByteArray());
173 }
174
175 /**
176 * @param oldname a JVM class name.
177 * @param newname a JVM class name.
178 */
179 void renameClass(String oldname, String newname) {
180 HashMap map = new HashMap();
181 map.put(oldname, newname);
182 renameClass(map);
183 }
184
185 void renameClass(Map classnames) {
186 Renamer renamer = new Renamer(info, getConstPool(), classnames);
187 try {
188 renamer.parameters();
189 } catch (Exception e) {
190 throw new RuntimeException(e);
191 }
192 }
193
194 void getRefClasses(Map classnames) { renameClass(classnames); }
195
196 /**
197 * Returns a string representation of this object.
198 */
199 public String toString() {
200 Annotation[][] aa = getAnnotations();
201 StringBuilder sbuf = new StringBuilder();
202 int k = 0;
203 while (k < aa.length) {
204 Annotation[] a = aa[k++];
205 int i = 0;
206 while (i < a.length) {
207 sbuf.append(a[i++].toString());
208 if (i != a.length)
209 sbuf.append(" ");
210 }
211
212 if (k != aa.length)
213 sbuf.append(", ");
214 }
215
216 return sbuf.toString();
217
218 }
219 }